
module spi3wire 
(
    input  clk_50M,
    input  reset_n,               // reset.reset
    
    input   [22:0]    avs_s0_address,     //    s0.address
    input             avs_s0_read,        //      .read
    input             avs_s0_write,       //      .write
    output reg [31:0] avs_s0_readdata,    //      .readdata
    input   [31:0]    avs_s0_writedata,   //      .writedata
    input             device_req,         //      .waitrequest
    output reg        device_ack,         //      .waitrequest
    input   [3:0]     avs_s0_byteenable,  //    .readdata

    output           spi_cs,
    output reg       spi_clk,
    inout            spi_dat
);

  assign spi_dat  = enableW ? out_dat : 1'bz;

  reg req;
  reg cs_req;
  
  reg [7:0] write_data;

  reg csVal;
  reg enableW;
  reg status;
  reg device_req_buff;
  always @ (posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      req <= 0;
      cs_req <= 0;

      avs_s0_readdata <= 0;
      status <= 0;
      
      csVal <= 0;

      device_req_buff <= 0;
      
      enableW <= 0;
      device_ack <= 0;
    end else begin

      device_req_buff <= device_req;

      if(device_req_buff && !device_ack)begin
        if(avs_s0_address[0]==0)begin
          if(status==0)begin
            status <= 1;
            req <= 1;
            write_data <= avs_s0_writedata[7:0];
            enableW <= avs_s0_write;
          end else begin
            if(ack)begin
              req <= 0;
              status <= 0;
              avs_s0_readdata <= {24'b0,read_data};
              enableW <= 0;
              device_ack <= 1;
            end
          end
        end else begin
          if(status==0)begin
            status <= 1;
            cs_req <= 1;
            csVal <= avs_s0_writedata[0];
          end else begin
            if(cs_ack)begin
              cs_req <= 0;
              status <= 0;
              device_ack <= 1;
            end
          end
        end
      end
      
      if(!device_req_buff && device_ack)begin
        device_ack <= 0;
      end
      
    end
  end

  assign spi_cs = CS;

  reg [7:0] read_data;
  reg [7:0] write_data_buff;
  reg [2:0] count;
  reg       state;
  reg CS;
  //reg  [15:0] dly;
  //wire [15:0] dly_max = 65535;
  reg [7:0] dly;
  wire [7:0] dly_max = 255;
  
  reg ack;
  reg cs_ack;
  reg out_dat;
  always @ (posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      CS <= 1'b0;
      spi_clk <= 0;
      ack <= 0;
      cs_ack <= 0;

      count <= 0;
      state <= 0;
      dly <= 0;
      read_data <= 0;
      write_data_buff <= 0;
    end else begin
      spi_clk <= 0;
      


      if(req && !ack)begin
        if(state==0)begin
          dly <= dly + 1'b1;
          if(dly==dly_max)begin
            dly <= 0;
            state <= 1;
          end 
          if(dly==0) begin
            if(count==0)begin
              out_dat <= write_data[0];
              write_data_buff <= {1'b0,write_data[7:1]};
            end else begin
              out_dat <= write_data_buff[0];
              write_data_buff <= {1'b0,write_data_buff[7:1]};
            end
          end
          if(dly==dly_max) begin
            read_data <= {spi_dat,read_data[7:1]};
          end
        end else begin
          spi_clk <= 1;
          dly <= dly + 1'b1;
          if(dly==dly_max)begin
            dly <= 0;
            count <= count + 1'b1;
            if(count == 7)begin
              count <= 0;
              ack <= 1;
            end
            state <= 0;
          end
        end
      end
      if(!req && ack)begin
        ack <= 0;
      end
      
      
      
      if(cs_req && !cs_ack)begin
        CS <= csVal;
        dly <= dly + 1'b1;
        if(dly==dly_max)begin
          dly <= 0;
          cs_ack <= 1;
        end 
      end
      if(!cs_req && cs_ack)begin
        cs_ack <= 0;
      end

    end
  end
  
  
endmodule
